#pragma once

#include "kwdb/point.h"
#include "kwdb/status.h"
#include <memory>
#include <vector>
#include <functional>
#include <atomic>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <queue>
#include <chrono>

namespace kwdb {

// Batch processor configuration
struct BatcherConfig {
    size_t max_batch_size = 1000;      // Maximum points per batch
    int linger_ms = 100;               // Maximum time to wait before flushing
    size_t max_pending_batches = 10;   // Maximum batches in queue (backpressure)

    // Load from environment if not explicitly set
    static BatcherConfig FromEnvironment();
};

// Callback type for batch processing
using BatchCallback = std::function<Status(const std::vector<Point>&)>;

class Batcher {
public:
    explicit Batcher(const BatcherConfig& config, BatchCallback callback);
    ~Batcher();

    // Add a single point (may block if max_pending_batches reached)
    Status Add(const Point& point);

    // Add multiple points (may block if max_pending_batches reached)
    Status Add(const std::vector<Point>& points);

    // Force flush all pending batches
    Status Flush();

    // Close the batcher and flush remaining data
    void Close();

    // Get current metrics
    size_t GetPendingCount() const { return pending_count_.load(); }
    size_t GetBatchesFlushed() const { return batches_flushed_.load(); }

private:
    void FlushThread();
    Status FlushBatch(std::vector<Point>&& batch);

    BatcherConfig config_;
    BatchCallback callback_;

    // Current accumulating batch
    std::vector<Point> current_batch_;
    std::mutex current_mutex_;

    // Queue for completed batches awaiting flush
    std::queue<std::vector<Point>> pending_batches_;
    std::mutex queue_mutex_;
    std::condition_variable queue_cv_;
    std::condition_variable backpressure_cv_;

    // Background flush thread
    std::thread flush_thread_;
    std::atomic<bool> running_{true};

    // Metrics
    std::atomic<size_t> pending_count_{0};
    std::atomic<size_t> batches_flushed_{0};

    // Timer for linger
    std::chrono::steady_clock::time_point last_add_time_;
};

} // namespace kwdb